<?php
// +-------------------------------------------------------------------
// | 
// +-------------------------------------------------------------------
// | Copyright (c) 2009-2016 All rights reserved.
// +-------------------------------------------------------------------
namespace Kcdns\Service\Api;

class Service
{

    protected $codes;
    
    // 调用接口
    public function call ($apiName, $param, $version = 'V1')
    {
        $this->codes = Code::$$version;
        
        // 校验接口名称合法性
        filter($apiName, 'required;pattern=/[a-zA-Z0-9_]/');
        
        // 检查接口文件
        $apiFile = __DIR__ . "/$version/$apiName.class.php";
        if (! file_exists($apiFile))
        {
            return $this->_response('invaid_action');
        }
        
        // 接口方法对象
        $apiClass = "\\Service\\Api\\$version\\$apiName";
        $apiInstance = new $apiClass();
        
        // 客户端 TOKEN : 通过 HTTP 请求头的 CTOKEN 项获取
        $apiOpenId = $_SERVER['HTTP_CTOKEN'];
        
        // 从 GET 参数中获取客户端 TOKEN, 浏览器调试用
        $apiOpenId or $apiOpenId = $_GET['t'];
        
        // 校验输入参数
        try
        {
            filter($apiOpenId, "required;pattern=/[a-zA-Z0-9_]{1,32}/");
            filter($param, $apiInstance->input);
        }
        catch (\Exception $e)
        {
            return $this->_response('invalid_param', null, $e->getMessage());
        }
        
        // 重置 session
        $sessionId = md5("HANMEI{$apiOpenId}");
        if (session_id() !== $sessionId)
        {
            session('[destroy]');
            session([
                    'id' => $sessionId
            ]);
            session_start();
        }
        
        // 构造客户端 Oauth2.0 信息
        $clientOauthInfo = [
                'type' => 'api',
                'openid' => $apiOpenId
        ];
        if (! M('oauth')->where($clientOauthInfo)->find())
        {
            $newClientOauthData = $clientOauthInfo;
            $newClientOauthData['token'] = '';
            $newClientOauthData['refresh_token'] = '';
            $newClientOauthData['data'] = '';
            $newClientOauthData['expires'] = 0;
            $newClientOauthData['create_time'] = date('Y-m-d H:i:s');
            M('oauth')->data($newClientOauthData)->add();
        }
        
        // 更新登录更新时间
        // 登录时间可用于长时间未登录后自动解除绑定关系
        M('oauth')->data(array_merge($clientOauthInfo, [
                'update_time' => date('Y-m-d H:i:s')
        ]))->where($clientOauthInfo)->save();
        
        // 设置当前客户端 Oauth2.0 信息
        O('user')->setOauth($clientOauthInfo);
        
        // 尝试使用客户端 Oauth2.0 信息自动登录
        O('user')->current() or O('user')->loginWithOauth($clientOauthInfo);
        
        // 注入用户信息
        $apiInstance->user = O('user')->current();

        // 检查接口方法是否需要用户登录
        if ($apiInstance->login and ! $apiInstance->user)
        {
            return $this->_response('not_login');
        }
        
        // 执行
        try
        {
            $output = $apiInstance->run($param);
            filter($output, $apiInstance->output);
            return $this->_response('ok', $output);
        }
        catch (\Exception $e)
        {
            return $this->_response($e->getMessage(), null, $e->getMessage());
        }
    }
    
    // 输出测试文档
    public function doc ($urlBase, $hosts = [], $version = 'V1')
    {
        return Doc::html($urlBase, $hosts, $version);
    }
    
    // 格式化响应
    protected function _response ($status, $data = null, $msg = '')
    {
        // 默认输出系统错误
        $status   = isset($this->codes[$status]) ? $status : 'default_error';
        $msg      = !isset($this->codes[$msg]) ? $msg : '';
        $response = array(
                'err_code' => $this->codes[$status][0],
                'err_msg' => (string) ($msg ? $msg : $this->codes[$status][1]),
                'data' => $data
        );
        return json_encode($response, JSON_UNESCAPED_UNICODE);
    }
}